#include <windows.h>
#define CMD_EXIT 109

HWND hFrame;
HHOOK keyHook = NULL;
const char *APP_NAME = "BlackBoard\0";
ACCEL KEY_TABLE[] = {
  {FVIRTKEY, VK_ESCAPE, CMD_EXIT}
};

void doCommand(HWND hWnd, WPARAM wParam) {
  switch (LOWORD(wParam)) {
  case CMD_EXIT:
    PostMessage(hWnd, WM_CLOSE, 0, 0);
    return;
  }
}

LRESULT CALLBACK defaultProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  switch (uMsg) {
  case WM_CLOSE:
    DestroyWindow(hWnd);
    break;
  case WM_COMMAND:
    doCommand(hWnd, wParam);
    break;
  case WM_DESTROY:
    PostQuitMessage(0);
    break;
  default:
    return DefWindowProc(hWnd, uMsg, wParam, lParam);
  }
}

LRESULT WINAPI hookProc(int nCode, WPARAM wParam, LPARAM lParam) {
  LPKBDLLHOOKSTRUCT p = (LPKBDLLHOOKSTRUCT)lParam;
  BOOL b = FALSE, isAlt = p->flags & LLKHF_ALTDOWN, isCtrl = GetKeyState(VK_CONTROL) & 0x8000;

  if (nCode == HC_ACTION) {
    switch (wParam) {
    case WM_KEYDOWN:
    case WM_KEYUP:
    case WM_SYSKEYDOWN:
    case WM_SYSKEYUP:
      b = (p->vkCode == VK_LWIN) || (p->vkCode == VK_RWIN) ||
      ((p->vkCode == VK_TAB) && isAlt) ||
      ((p->vkCode == VK_ESCAPE) && isCtrl) ||
      ((p->vkCode == VK_ESCAPE) && isAlt) ||
      (p->vkCode >= 65 && p->vkCode <= 90);
      break;
    default:
      break;
    }
  }

  return (b ? TRUE : CallNextHookEx(keyHook, nCode, wParam, lParam)) ;
}

HWND createFrame(HINSTANCE hInstance) {
  WNDCLASS wc;
  wc.style = CS_HREDRAW | CS_VREDRAW;
  wc.lpfnWndProc = defaultProc;
  wc.cbClsExtra = 0;
  wc.cbWndExtra = 0;
  wc.hbrBackground = CreateSolidBrush(BLACK_BRUSH);
  wc.hCursor = NULL;
  wc.hIcon = NULL;
  wc.hInstance = hInstance;
  wc.lpszClassName = APP_NAME;
  wc.lpszMenuName = NULL;
  RegisterClass(&wc);

  return CreateWindowEx(
    WS_EX_TOPMOST,
    APP_NAME,
    APP_NAME,
    WS_POPUP | WS_VISIBLE,
    0,
    0,
    GetSystemMetrics(SM_CXSCREEN),
    GetSystemMetrics(SM_CYSCREEN),
    0,
    0,
    hInstance,
    NULL
  );
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
  HACCEL hAccel = CreateAcceleratorTable(KEY_TABLE, sizeof(KEY_TABLE) / sizeof(ACCEL));
  hFrame = createFrame(hInstance);
  keyHook = SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, GetModuleHandle(NULL), 0);
  SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED);
  SendMessage(hFrame, WM_SYSCOMMAND, SC_MONITORPOWER, 2);
  ShowCursor(FALSE);

  MSG msg;
  ZeroMemory(&msg, sizeof(msg));
  while (GetMessage(&msg, NULL, 0, 0)) {
    if (!TranslateAccelerator(hFrame, hAccel, &msg)) {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
  }

  UnregisterClass(APP_NAME, hInstance);
  UnhookWindowsHookEx(keyHook);
  DestroyAcceleratorTable(hAccel);
  return msg.wParam;
}